/*
 *    Copyright 2022 Huawei Technologies Co., Ltd.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package org.edgegallery.website.config;

import java.io.IOException;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

@Component
public class FilterPostProcessor implements BeanPostProcessor {

    private static final Logger LOGGER = LoggerFactory.getLogger(FilterPostProcessor.class);

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        LOGGER.info("postProcessAfterInitialization starting.");
        if (bean instanceof FilterChainProxy) {
            FilterChainProxy chains = (FilterChainProxy) bean;
            chains.getFilterChains().forEach(chain -> {
                chain.getFilters().forEach(filter -> {
                    if (filter instanceof OAuth2ClientAuthenticationProcessingFilter) {
                        setFilterAuthenticationSuccessHandler(filter);
                    }
                });
            });
        }
        return bean;
    }

    private void setFilterAuthenticationSuccessHandler(Filter filter) {
        LOGGER.info("OAuth2ClientAuthenticationProcessingFilter starting.");
        ((OAuth2ClientAuthenticationProcessingFilter) filter).setAuthenticationSuccessHandler(
            new SimpleUrlAuthenticationSuccessHandler() {
                public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                    Authentication authentication) throws IOException, ServletException {
                    LOGGER.info("onAuthenticationSuccess.");
                    HttpSession session = request.getSession(false);
                    OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
                    ServletContext servletContext = ClientApplicationContext.getBean(ServletContext.class);
                    TokenStore jwtTokenStore = ClientApplicationContext.getBean(TokenStore.class);
                    Map<String, Object> additionalInformation = jwtTokenStore.readAccessToken(details.getTokenValue())
                        .getAdditionalInformation();
                    servletContext.setAttribute(additionalInformation.get("ssoSessionId").toString(), session);
                    super.onAuthenticationSuccess(request, response, authentication);
                }
            });
        LOGGER.info("OAuth2ClientAuthenticationProcessingFilter end.");
    }

}
